/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "GtkBookList.h"
//#define _DEBUG_


GtkBookList::GtkBookList()
: numitems(0)
{
  // Attach the liststore to the treeview.
  store = Gtk::ListStore::create(columns);
  store->set_sort_column_id(columns.author_and_title, Gtk::SORT_ASCENDING);
  set_model(store);
  set_rules_hint();
  set_headers_visible(TRUE);
  set_headers_clickable();
  
  // Load the icons.
  pixbuf_book = Gdk::Pixbuf::create_from_file(PACKAGE_PIXMAPS_DIR "/book.png");
  pixbuf_rating.push_back(
               Gdk::Pixbuf::create_from_file(PACKAGE_PIXMAPS_DIR "/empty.png"));
  int i = 0;
  for (i = 0; i <= 10; i++) {
    char imgfile[2000];
    snprintf(imgfile, 2000, PACKAGE_PIXMAPS_DIR "/stars%i.png", i);
    pixbuf_rating.push_back(Gdk::Pixbuf::create_from_file(imgfile));
  }
  
  // Create a cell renderer and pack it into the "Author and Title" column.
  Gtk::TreeView::Column* col = Gtk::manage(
                              new Gtk::TreeView::Column(_("Author and Title")));
  col->pack_start(columns.icon,             FALSE);
  col->pack_start(columns.author_and_title, TRUE);
  
  // Enable pango markup language for the text renderer and change the layout
  // for the icon renderer.
  std::vector<Gtk::CellRenderer*> rends = col->get_cell_renderers();
  rends[0]->set_fixed_size(60, 48);
  col->clear_attributes(*rends[1]);
  col->add_attribute(*rends[1], "markup", 1);
  rends[1]->property_yalign() = 0.3;
  
  // Append all columns.
  append_column(*col);
  get_column(0)->set_resizable(TRUE);
  get_column(0)->set_sort_column_id(GTKBOOKLIST_COLUMN_AUTHORANDTITLE);
  append_column(_("Category"), columns.category);
  get_column(1)->set_resizable(TRUE);
  get_column(1)->set_sort_column_id(GTKBOOKLIST_COLUMN_CATEGORY);
  append_column(_("Read on..."), columns.readdate);
  get_column(2)->set_resizable(TRUE);
  get_column(2)->set_sort_column_id(GTKBOOKLIST_COLUMN_READDATE_TIMET);
  append_column(_("Rating"),    columns.rating);
  get_column(3)->get_first_cell_renderer()->property_xalign() = 0;
  get_column(3)->set_resizable(FALSE);
  get_column(3)->set_sort_column_id(GTKBOOKLIST_COLUMN_RATING_INT);
  
  signal_row_activated().connect(
                    sigc::mem_fun(*this, &GtkBookList::on_selection_activated));
  get_selection()->signal_changed().connect(
                    sigc::mem_fun(*this, &GtkBookList::on_selection_changed));
  store->signal_sort_column_changed().connect(signal_sorting_changed);
}


GtkBookList::~GtkBookList()
{
}


void GtkBookList::insert_book(Book* book)
{
  Gtk::TreeIter iter = store->append();
  Gtk::TreeRow  row  = *iter;
  row_fill(row, book);
  booklist[book] = iter;
  numitems++;
  signal_changed.emit();
}


void GtkBookList::remove_book(Book* book)
{
#ifdef _DEBUG_
  printf("GtkBookList::remove_book(): %s\n", book->get_title().c_str());
#endif
  g_assert(booklist.find(book) != booklist.end());
  Gtk::TreeIter iter = booklist.find(book)->second;
  store->erase(iter);
  booklist.erase(book);
  numitems--;
  signal_changed.emit();
}


void GtkBookList::remove_selected(void)
{
#ifdef _DEBUG_
  printf("GtkBookList::remove_selected(): Called.\n");
#endif
  Gtk::TreeIter iter = get_selection()->get_selected();
  if (!iter)
    return;
  Book* book = iter->get_value(columns.book);
  store->erase(iter);
  booklist.erase(book);
  numitems--;
  signal_changed.emit();
}


void GtkBookList::update_soft(void)
{
  std::map<Book*, Gtk::TreeIter>::iterator iter = booklist.begin();
  while (iter != booklist.end()) {
    Book*        book = iter->first;
    Gtk::TreeRow row  = *iter->second;
    row_fill(row, book);
    iter++;
  }
}


Book* GtkBookList::get_first_selected(void)
{
  if (!get_selection()->get_selected())
    return NULL;
  return get_selection()->get_selected()->get_value(columns.book);
}


int GtkBookList::get_numitems(void)
{
  return numitems;
}


void GtkBookList::set_sorting(int col)
{
  int           curcol;
  Gtk::SortType order;
  store->get_sort_column_id(curcol, order);
  if (curcol == col)
    return;
  store->set_sort_column_id(col, Gtk::SORT_ASCENDING);
}


int GtkBookList::get_sorting(void)
{
  int           col;
  Gtk::SortType order;
  store->get_sort_column_id(col, order);
  return col;
}


void GtkBookList::row_fill(Gtk::TreeModel::Row &row, Book* book)
{
  struct tm time = book->get_readdate();
  row[columns.icon]             = pixbuf_book;
  row[columns.author_and_title] = "<b>" + book->get_author() + "</b>\n"
                                + book->get_title();
  row[columns.title]            = book->get_title();
  row[columns.category]         = book->get_category();
  row[columns.readdate]         = book->get_readdate_string();
  row[columns.readdate_time_t]  = mktime(&time);
  row[columns.rating]           = pixbuf_rating[book->get_rating() + 1];
  row[columns.rating_integer]   = book->get_rating();
  row[columns.book]             = book;
}


void GtkBookList::on_selection_activated(Gtk::TreePath path,
                                         Gtk::TreeViewColumn* column)
{
  Book* book = store->get_iter(path)->get_value(columns.book);
  signal_book_activated.emit(book);
}


void GtkBookList::on_selection_changed(void)
{
  Gtk::TreeIter iter = get_selection()->get_selected();
  if (!iter)
    return;
  Book* book = iter->get_value(columns.book);
  signal_book_selected.emit(book);
}
